package net.goutalk.glcs.module.erpModel.caseErpSale.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import net.goutalk.glcs.common.annotation.GlcsLog;
import net.goutalk.glcs.common.constant.GlobalConstant;
import net.goutalk.glcs.common.enums.YesOrNoEnum;
import net.goutalk.glcs.common.model.result.R;
import net.goutalk.glcs.common.utils.RedisUtil;
import net.goutalk.glcs.module.erpModel.caseErpCustomer.entity.CaseErpCustomer;
import net.goutalk.glcs.module.erpModel.caseErpCustomer.service.ICaseErpCustomerService;
import net.goutalk.glcs.module.erpModel.caseErpLog.entity.CaseErpLog;
import net.goutalk.glcs.module.erpModel.caseErpLog.service.ICaseErpLogService;
import net.goutalk.glcs.module.erpModel.caseErpSale.entity.CaseErpSale;
import net.goutalk.glcs.module.erpModel.caseErpSale.entity.CaseErpSaleDetail;
import net.goutalk.glcs.module.erpModel.caseErpSale.service.ICaseErpSaleDetailService;
import net.goutalk.glcs.module.erpModel.caseErpSale.service.ICaseErpSaleService;
import net.goutalk.glcs.module.erpModel.caseErpSale.utils.DataBuildUtil;
import net.goutalk.glcs.module.erpModel.caseErpSale.vo.*;
import net.goutalk.glcs.module.erpModel.caseErpStore.entity.CaseErpStoreReceipt;
import net.goutalk.glcs.module.erpModel.caseErpStore.service.ICaseErpStoreReceiptService;
import net.goutalk.glcs.module.organization.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import net.goutalk.glcs.module.erpModel.caseErpSale.dto.AddCaseErpSaleDto;
import net.goutalk.glcs.module.erpModel.caseErpSale.dto.CaseErpSalePageDto;
import net.goutalk.glcs.module.erpModel.caseErpSale.dto.ExportDto;
import net.goutalk.glcs.module.erpModel.caseErpSale.dto.UpdateCaseErpSaleDto;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 销售订单信息【case_erp_sale】 前端控制器
 * </p>
 *
 * @author hnyyzy
 * @since 2023-07-17
 */
@RestController
@RequestMapping(GlobalConstant.CASE_ERP_SALE +"/caseErpSale")
@Api(value = GlobalConstant.CASE_ERP_SALE +"/caseErpSale", tags = "销售订单信息")
@AllArgsConstructor
public class CaseErpSaleController {

    private ICaseErpSaleService caseErpSaleService;

    private ICaseErpSaleDetailService caseErpSaleDetailService;

    private ICaseErpLogService caseErpLogService;

    private ICaseErpCustomerService caseErpCustomerService;

    private RedisUtil redisUtil;

    private ICaseErpStoreReceiptService caseErpStoreReceiptService;

    @GetMapping(value = "/list")
    @ApiOperation("销售订单信息列表")
    public R list(CaseErpSalePageDto dto) {
        List<CaseErpSale> list = caseErpSaleService.list(Wrappers.<CaseErpSale>query().lambda()
                .like(StrUtil.isNotBlank(dto.getTheme()),CaseErpSale::getTheme,dto.getTheme())
                .or()
                .like(StrUtil.isNotBlank(dto.getTheme()),CaseErpSale::getSaleNumber,dto.getTheme())
        );
        List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
        });
        List<CaseErpSaleListVo> caseErpSaleListVoList = BeanUtil.copyToList(list, CaseErpSaleListVo.class);
        for (CaseErpSaleListVo caseErpSaleListVo : caseErpSaleListVoList) {
            if (ObjectUtil.isNotEmpty(caseErpSaleListVo.getCreateUserId())){
                final User user = userList.stream().filter(x -> x.getId().equals(caseErpSaleListVo.getCreateUserId())).findFirst().orElse(new User());
                if (StrUtil.isNotBlank(user.getName())){
                    caseErpSaleListVo.setCreateUserName(user.getName());
                }
            }
        }
        return R.ok(caseErpSaleListVoList);
    }

    @GetMapping(value = "/page")
    @ApiOperation("销售订单信息列表分页")
    public R page(CaseErpSalePageDto dto) {
        return R.ok(caseErpSaleService.getPageList(dto));
    }

    @GetMapping("/code")
    @ApiOperation(value = "生成销售单号")
    public R genCode() {
        StringBuilder result = new StringBuilder("PRO");
        String dateStr = DateUtil.format(new Date(), "yyyMMdd");
        result.append(dateStr);
        result.append(RandomUtil.randomNumbers(9));
        return R.ok(result.toString());
    }

    @PostMapping
    @ApiOperation(value = "新增订单申请")
    @Transactional
    public R add(@RequestBody AddCaseErpSaleDto dto) {
        CaseErpSale sale = BeanUtil.toBean(dto, CaseErpSale.class);
        if (ObjectUtil.isNotEmpty(dto.getIsSysNumBoolean()) && dto.getIsSysNumBoolean()){
            sale.setIsSysNum(YesOrNoEnum.YES.getCode());
        }else {
            sale.setIsSysNum(YesOrNoEnum.NO.getCode());
        }
        if (ObjectUtil.isNotEmpty(dto.getCustomerId())){
            CaseErpCustomer caseErpCustomer = caseErpCustomerService.getById(dto.getCustomerId());
            if (StrUtil.isNotBlank(caseErpCustomer.getName())){
                sale.setCustomerName(caseErpCustomer.getName());
            }
        }
        // 默认出入未完成
        sale.setOutStoreState(YesOrNoEnum.NO.getCode());
        // 默认到票状态未完成
        sale.setTicketState(YesOrNoEnum.NO.getCode());
        // 默认付款状态未完成
        sale.setPayState(YesOrNoEnum.NO.getCode());
        sale.setAlreadyAmount(BigDecimal.ZERO);
        sale.setAlreadyTicket(BigDecimal.ZERO);
        caseErpSaleService.save(sale);

        List<CaseErpSaleDetail> caseErpSaledetails = BeanUtil.copyToList(dto.getAddCaseErpSaleDetailDtoList(), CaseErpSaleDetail.class);
        if (CollectionUtil.isNotEmpty(caseErpSaledetails)) {
            caseErpSaledetails.stream().forEach(detail -> {
                detail.setSaleId(sale.getId());
                detail.setInStoreCount(BigDecimal.ZERO);
                detail.setNoInStoreCount(BigDecimal.ZERO);
                detail.setReturnCount(BigDecimal.ZERO);
                detail.setPlanCount(BigDecimal.ZERO);
            });
            caseErpSaleDetailService.saveBatch(caseErpSaledetails);
        }

        CaseErpLog log = new CaseErpLog();
        log.setKeyId(sale.getId());
        log.setCategoryId(0);
        log.setExecuteResultJson("新增订单申请");
        caseErpLogService.save(log);

        return R.ok(true);
    }

    @PutMapping
    @ApiOperation(value = "修改订单申请")
    @Transactional
    public R update(@Valid @RequestBody UpdateCaseErpSaleDto dto) {
        CaseErpSale sale = BeanUtil.toBean(dto, CaseErpSale.class);
        if (ObjectUtil.isNotEmpty(dto.getIsSysNumBoolean()) && dto.getIsSysNumBoolean()){
            sale.setIsSysNum(YesOrNoEnum.YES.getCode());
        }else {
            sale.setIsSysNum(YesOrNoEnum.NO.getCode());
        }
        if (ObjectUtil.isNotEmpty(dto.getCustomerId())){
            CaseErpCustomer caseErpCustomer = caseErpCustomerService.getById(dto.getCustomerId());
            if (StrUtil.isNotBlank(caseErpCustomer.getName())){
                sale.setCustomerName(caseErpCustomer.getName());
            }
        }
        caseErpSaleService.updateById(sale);
        //先删除所有详情再新增
        if (CollectionUtil.isNotEmpty(dto.getAddCaseErpSaleDetailDtoList())){
            caseErpSaleDetailService.remove(Wrappers.lambdaQuery(CaseErpSaleDetail.class).eq(CaseErpSaleDetail::getSaleId, sale.getId()));

            List<CaseErpSaleDetail> caseErpSaledetails = BeanUtil.copyToList(dto.getAddCaseErpSaleDetailDtoList(), CaseErpSaleDetail.class);
            if (CollectionUtil.isNotEmpty(caseErpSaledetails)) {
                caseErpSaledetails.stream().forEach(detail -> {
                    detail.setSaleId(sale.getId());
                    detail.setInStoreCount(BigDecimal.ZERO);
                    detail.setNoInStoreCount(BigDecimal.ZERO);
                    detail.setReturnCount(BigDecimal.ZERO);
                    detail.setPlanCount(BigDecimal.ZERO);
                });
            }
            caseErpSaleDetailService.saveOrUpdateBatch(caseErpSaledetails);

        }else {
            caseErpSaleDetailService.remove(Wrappers.lambdaQuery(CaseErpSaleDetail.class).eq(CaseErpSaleDetail::getSaleId, sale.getId()));
        }

        CaseErpLog log = new CaseErpLog();
        log.setKeyId(sale.getId());
        log.setCategoryId(0);
        log.setExecuteResultJson("修改订单申请");
        caseErpLogService.save(log);
        return R.ok(true);
    }


    @GetMapping(value = "/info")
    @ApiOperation(value = "根据id查询销售订单信息（返回id值，编辑使用）")
    public R info(@RequestParam Long id) {
        CaseErpSale caseErpSale = caseErpSaleService.getById(id);
        if (caseErpSale == null) {
            R.error("找不到此销售订单信息！");
        }
        CaseErpSaleInfoVo caseErpSaleInfoVo = BeanUtil.toBean(caseErpSale, CaseErpSaleInfoVo.class);
        if (ObjectUtil.isNotEmpty(caseErpSaleInfoVo.getIsSysNum()) && caseErpSaleInfoVo.getIsSysNum() == YesOrNoEnum.YES.getCode()){
            caseErpSaleInfoVo.setIsSysNumBoolean(true);
        }else {
            caseErpSaleInfoVo.setIsSysNumBoolean(false);
        }
        List<CaseErpSaleDetail> list = caseErpSaleDetailService.list(Wrappers.<CaseErpSaleDetail>query().lambda().eq(CaseErpSaleDetail::getSaleId, caseErpSale.getId()));
        caseErpSaleInfoVo.setCaseErpSaleDetailList(list);
        return R.ok(caseErpSaleInfoVo);
    }

    @DeleteMapping
    @ApiOperation(value = "删除")
    @GlcsLog(value = "删除订单信息")
    public R delete(@Valid @RequestBody Long id) {
        caseErpSaleService.removeById(id);
        caseErpSaleDetailService.remove(Wrappers.<CaseErpSaleDetail>query().lambda().eq(CaseErpSaleDetail::getSaleId,id));
        return R.ok(true);
    }


    @PostMapping(value = "/export")
    @ApiOperation(value = "导出")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> export(@RequestBody List<Long> ids) {
        List<CaseErpSale> list = caseErpSaleService.list(Wrappers.<CaseErpSale>query().lambda().in(CaseErpSale::getId,ids));
        List<CaseErpSaleDetail> saleDetailList = caseErpSaleDetailService.list();
        List<CaseErpSalePageVo> salePageVoList = BeanUtil.copyToList(list, CaseErpSalePageVo.class);
        for (CaseErpSalePageVo caseErpSalePageVo : salePageVoList) {
            StringBuilder detailStr = new StringBuilder();
            for (CaseErpSaleDetail saleDetail : saleDetailList) {
                if (ObjectUtil.equals(caseErpSalePageVo.getId(), saleDetail.getSaleId())) {
                    detailStr.append(StringPool.COMMA);
                    detailStr.append(saleDetail.getName());
                    detailStr.append(StringPool.COLON + StringPool.SPACE);
                    detailStr.append(String.format("%.0f", saleDetail.getCount()));
                }
            }
            if (detailStr.length() > 0) {
                detailStr.delete(0, 1);
            }
            caseErpSalePageVo.setSaleDetail(detailStr.toString());
        }
        List<CaseErpSaleExportVo> saleExportVoList = BeanUtil.copyToList(salePageVoList, CaseErpSaleExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, CaseErpSaleExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "销售订单列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @GetMapping(value = "/check-info")
    @ApiOperation(value = "根据id查询销售订单信息（返回id值，供查看使用）")
    public R checkInfo(@RequestParam Long id) {
        return R.ok(caseErpSaleService.checkInfo(id));
    }

    @PostMapping(value = "/export-sale-detail")
    @ApiOperation(value = "导出销售详情数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpSaleDetail(@RequestBody ExportDto dto) {
        List<CaseErpSaleDetail> saledetailList = caseErpSaleDetailService.list(Wrappers.lambdaQuery(CaseErpSaleDetail.class).in(CaseErpSaleDetail::getId, dto.getIds()));
        List<CaseErpSaleDetailExportVo> saleExportVoList = BeanUtil.copyToList(saledetailList, CaseErpSaleDetailExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, CaseErpSaleDetailExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "产品明细列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @PostMapping(value = "/export-sale-out")
    @ApiOperation(value = "导出销售出库数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpSaleOut(@RequestBody ExportDto dto) {
        //拿销售的id去出入库单据表查询，有无关联数据，有的话就展示
        List<OutStoreVo> outStoreVos = new ArrayList<>();
        List<CaseErpStoreReceipt> list = caseErpStoreReceiptService.list(Wrappers.<CaseErpStoreReceipt>query().lambda().eq(CaseErpStoreReceipt::getRelationKeyId, dto.getSaleId()));
        if (CollectionUtil.isNotEmpty(list)){//真数据
            for (CaseErpStoreReceipt caseErpStoreReceipt : list) {
                OutStoreVo outStoreVo = new OutStoreVo();
                outStoreVo.setId(caseErpStoreReceipt.getId());
                outStoreVo.setCode(caseErpStoreReceipt.getCode());
                outStoreVo.setTheme(caseErpStoreReceipt.getName());
                outStoreVo.setDate(caseErpStoreReceipt.getCreateDate());
                outStoreVo.setName("客户一");
                outStoreVo.setPerson(caseErpStoreReceipt.getPersonNames());
                outStoreVo.setStore("仓库一");
                outStoreVos.add(outStoreVo);
            }
        }
        List<OutStoreVo> collect = outStoreVos.stream().filter(x -> dto.getIds().contains(x.getId())).collect(Collectors.toList());
        List<OutStoreExportVo> saleExportVoList = BeanUtil.copyToList(collect, OutStoreExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, OutStoreExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "销售出库记录列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @PostMapping(value = "/export-sale-invoice")
    @ApiOperation(value = "导出销售开票记录数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpSaleInvoice(@RequestBody ExportDto dto) {
        List<InvoiceVo> invoiceVos = DataBuildUtil.buildInvoiceLogList(dto.getSaleId());
        List<InvoiceVo> collect = invoiceVos.stream().filter(x -> dto.getIds().contains(x.getId())).collect(Collectors.toList());
        List<InvoiceExportVo> saleExportVoList = BeanUtil.copyToList(collect, InvoiceExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, InvoiceExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "销售开票记录列表" + ExcelTypeEnum.XLSX.getValue());
    }


    @PostMapping(value = "/export-sale-collection")
    @ApiOperation(value = "导出销售收款记录数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpSaleCollection(@RequestBody ExportDto dto) {
        List<CollectionVo> collectionVos = DataBuildUtil.buildCollectionVoList(dto.getSaleId());
        List<CollectionVo> collect = collectionVos.stream().filter(x -> dto.getIds().contains(x.getId())).collect(Collectors.toList());
        List<CollectionExportVo> saleExportVoList = BeanUtil.copyToList(collect, CollectionExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, CollectionExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "销售收款记录列表" + ExcelTypeEnum.XLSX.getValue());
    }


    @PostMapping(value = "/export-sale-product")
    @ApiOperation(value = "导出销售生产记录数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpSaleProduct(@RequestBody ExportDto dto) {
        List<ProductVo> collectionVos = DataBuildUtil.buildProductLogList(dto.getSaleId());
        List<ProductVo> collect = collectionVos.stream().filter(x -> dto.getIds().contains(x.getId())).collect(Collectors.toList());
        List<ProductExportVo> saleExportVoList = BeanUtil.copyToList(collect, ProductExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, ProductExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "销售生产记录列表" + ExcelTypeEnum.XLSX.getValue());
    }

    @PostMapping(value = "/export-sale-log")
    @ApiOperation(value = "导出销售操作记录数据")
    @GlcsLog(value = "导出表单数据")
    public ResponseEntity<byte[]> exportCaseErpSaleLog(@RequestBody ExportDto dto) {
        List<CaseErpLog> logList = caseErpLogService.list(Wrappers.lambdaQuery(CaseErpLog.class).eq(CaseErpLog::getKeyId, dto.getSaleId()));
        List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
        });
        for (CaseErpLog caseErpLog : logList) {
            if (ObjectUtil.isNotEmpty(caseErpLog.getCreateUserId())){
                User user = userList.stream().filter(x -> x.getId().equals(caseErpLog.getCreateUserId())).findFirst().orElse(new User());
                if (StrUtil.isNotBlank(user.getName())){
                    caseErpLog.setOperateUserAccount(user.getName());
                }
            }
        }
        List<LogExportVo> saleExportVoList = BeanUtil.copyToList(logList, LogExportVo.class);
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, LogExportVo.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(saleExportVoList);
        return R.fileStream(bot.toByteArray(), "销售操作记录列表" + ExcelTypeEnum.XLSX.getValue());
    }

}
